package com.imis.module.system.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imis.base.constant.CommonConstant;
import com.imis.base.constant.DataBaseConstant;
import com.imis.module.base.impl.BaseServiceImpl;
import com.imis.module.system.dao.SysMenuMapper;
import com.imis.module.system.model.converter.SysMenuConverter;
import com.imis.module.system.model.po.SysMenu;
import com.imis.module.system.model.ro.PagingQueryMenuDTO;
import com.imis.module.system.model.ro.QueryMenuDTO;
import com.imis.module.system.model.ro.SysMenuUpdateRO;
import com.imis.module.system.model.vo.DropDownBoxTreeVO;
import com.imis.module.system.model.vo.SysMenuTreeVO;
import com.imis.module.system.model.vo.SysMenuVO;
import com.imis.module.system.service.ISysMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 功能菜单表 服务实现类
 * </p>
 *
 * @author XinLau
 * @since 2020-03-17
 */
@Service
@Slf4j
@DS(DataBaseConstant.DATA_SOURCE_MASTER)
public class SysMenuServiceImpl extends BaseServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {

    /**
     * 生成功能菜单Tree
     *
     * @param sysMenuParentList - 功能菜单对象集合
     * @return List<SysMenuTreeVO> - 功能菜单Tree
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    private List<SysMenuTreeVO> querySysMenuTreeForPagingQuery(List<SysMenuTreeVO> sysMenuParentList) {
        /**
         * 此处这样操作完全是因为分页查询只分页查询一级菜单
         */
        List<SysMenuTreeVO> sysMenuTreeVOList = new ArrayList<>();
//        1.查询所有非一级功能菜单
        List<SysMenu> sysMenuList = mapper.selectList(Wrappers.<SysMenu>lambdaQuery().ne(SysMenu::getParentId, 0L).orderByAsc(SysMenu::getSortNo).orderByDesc(SysMenu::getCreateTime));
        if (sysMenuParentList.size() > 0) {
            for (SysMenuTreeVO sysMenuParen : sysMenuParentList) {
                sysMenuTreeVOList.add(findChildMenu(sysMenuParen, SysMenuConverter.INSTANCE.listPo2listTreeVo(sysMenuList)));
            }
        }
        return sysMenuTreeVOList;
    }

    /**
     * 递归查找子节点
     *
     * @param sysMenuTreeVO     - 父对象
     * @param sysMenuTreeVOList - 集合对象
     * @return SysMenuTreeVO -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/23 15:37
     */
    private SysMenuTreeVO findChildMenu(SysMenuTreeVO sysMenuTreeVO, List<SysMenuTreeVO> sysMenuTreeVOList) {
        for (SysMenuTreeVO sysMenu : sysMenuTreeVOList) {
//            1.判断父对象的编号是不是等于子对象的父编号
            if (sysMenuTreeVO.getId().equals(sysMenu.getParentId())) {
//                2_1.判断父对象内的字段项为空时的操作
                if (sysMenuTreeVO.getChildMenu() == null) {
                    sysMenuTreeVO.setChildMenu(new ArrayList<SysMenuTreeVO>());
                }
//                2_2.递归查找子节点
                sysMenuTreeVO.getChildMenu().add(findChildMenu(sysMenu, sysMenuTreeVOList));
            }
        }
        return sysMenuTreeVO;
    }

    /**
     * 生成功能菜单Tree
     *
     * @param sysMenuList - 功能菜单对象集合
     * @return List<SysMenuTreeVO> - 功能菜单Tree
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    private List<SysMenuTreeVO> querySysMenuTree(List<SysMenuTreeVO> sysMenuList) {
        List<SysMenuTreeVO> sysMenuTreeVOList = new ArrayList<>();
        for (SysMenuTreeVO sysMenuTreeVO : sysMenuList) {
            boolean addTheNode = Boolean.TRUE;
            for (SysMenuTreeVO sysMenuVO : sysMenuList) {
                if (sysMenuTreeVO.getParentId() != null && sysMenuTreeVO.getParentId().equals(sysMenuVO.getId())){
                    addTheNode = false;
                    if (sysMenuVO.getChildMenu() == null) {
                        sysMenuVO.setChildMenu(new ArrayList<SysMenuTreeVO>());
                    }
                    sysMenuVO.getChildMenu().add(sysMenuTreeVO);
                }
            }
            if (addTheNode) {
                sysMenuTreeVOList.add(sysMenuTreeVO);
            }
        }
        return sysMenuTreeVOList;
    }

    /**
     * 生成下拉树
     *
     * @param dropDownBoxTreeVOList - 集合对象
     * @return List<DropDownBoxTreeVO> -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/23 15:37
     */
    private List<DropDownBoxTreeVO> generateDropDownBoxTree(List<DropDownBoxTreeVO> dropDownBoxTreeVOList) {
        List<DropDownBoxTreeVO> downBoxTreeVOList = new ArrayList<DropDownBoxTreeVO>();
        for (DropDownBoxTreeVO downBoxTreeVO : dropDownBoxTreeVOList) {
            boolean addTheNode = Boolean.TRUE;
            for (DropDownBoxTreeVO downBoxTree : dropDownBoxTreeVOList) {
                if (downBoxTreeVO.getParentId() != null && downBoxTreeVO.getParentId().equals(downBoxTree.getKey())){
                    addTheNode = false;
                    if (downBoxTree.getChildren() == null) {
                        downBoxTree.setChildren(new ArrayList<DropDownBoxTreeVO>());
                    }
                    downBoxTree.getChildren().add(downBoxTreeVO);
                }
            }
            if (addTheNode) {
                downBoxTreeVOList.add(downBoxTreeVO);
            }
        }
        return downBoxTreeVOList;
    }

    /**
     * 分页查询功能菜单
     *
     * @param pagingQueryMenuDTO - 功能菜单查询对象
     * @return Page<SysMenuVO> - 分页功能菜单
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    @Override
    public Page<SysMenuTreeVO> pagingQuerySysMenuParentListByParameter(final PagingQueryMenuDTO pagingQueryMenuDTO) {
//        1.页码、页长
        Page<SysMenu> sysMenuPage = new Page<>(pagingQueryMenuDTO.getPageNumber(), pagingQueryMenuDTO.getPageSize());
//        2.排序字段
        sysMenuPage.addOrder(OrderItem.asc("sort_no"), OrderItem.desc(DataBaseConstant.CREATE_TIME_TABLE), OrderItem.desc(DataBaseConstant.UPDATE_TIME_TABLE));
//        3.条件分页查询
        sysMenuPage = mapper.pagingQuerySysMenuParentListByParameter(sysMenuPage, pagingQueryMenuDTO);
//        4.PO分页对象转VO实体分页对象
        Page<SysMenuTreeVO> sysMenuTreeVOPage = SysMenuConverter.INSTANCE.pagePo2pageTreeVo(sysMenuPage);
//        5.配置生成功能菜单Tree
        sysMenuTreeVOPage.setRecords(querySysMenuTreeForPagingQuery(sysMenuTreeVOPage.getRecords()));
//        6.返回值
        return sysMenuTreeVOPage;
    }

    /**
     * 查询功能菜单树
     *
     * @return List<SysMenuTreeVO>
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    @Override
    public List<SysMenuTreeVO> querySysMenuTreeListByParameter(final QueryMenuDTO queryMenuDTO) {
        List<SysMenu> sysMenuList = mapper.querySysMenuListByParameter(queryMenuDTO);
//        生成功能菜单Tree
        return querySysMenuTree(SysMenuConverter.INSTANCE.listPo2listTreeVo(sysMenuList));
    }

    /**
     * 查询指定角色的功能菜单树
     *
     * @param userId             - 用户编号
     * @param roleIdListByUserId - 角色编号
     * @return List<SysMenuTreeVO>
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/23 10:50
     */
    @Override
    public List<SysMenuTreeVO> querySysMenuTreeListByRoleIdList(final Long userId, final List<Long> roleIdListByUserId) {
//        1.根据角色编号查询功能能菜单
        List<SysMenu> sysMenuList = mapper.querySysMenuTreeListByRoleIdList(roleIdListByUserId);
//        2..生成Tree并返回
        return querySysMenuTree(SysMenuConverter.INSTANCE.listPo2listTreeVo(sysMenuList));
    }

    /**
     * 查询指定角色的功能菜单树
     *
     * @param roleIdentification - 角色编号
     * @return List<SysMenuTreeVO>
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/23 10:50
     */
    @Override
    public List<SysMenuTreeVO> querySysMenuTreeListByRoleId(final Long roleIdentification) {
//        1.根据角色编号查询功能能菜单
        List<SysMenu> sysMenuList = mapper.querySysMenuTreeListByRoleId(roleIdentification);
//        2..生成Tree并返回
        return querySysMenuTree(SysMenuConverter.INSTANCE.listPo2listTreeVo(sysMenuList));
    }

    /**
     * 根据功能菜单名查询功能菜单
     *
     * @param menuName - 功能菜单名称
     * @return SysMenu - 功能菜单
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    @Override
    public SysMenu queryMenuByName(final String menuName) {
//        按钮允许存在重复
        return mapper.selectOne(Wrappers.<SysMenu>lambdaQuery().eq(SysMenu::getName, menuName).ne(SysMenu::getMenuType, 2L));
    }

    /**
     * 根据功能菜单编号查询角色编号
     *
     * @param menuIdentification - 功能菜单标识
     * @return Long[]
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/16 09:30
     */
    @Override
    public Long[] selectSysRoleIdArrayByMenuId(final Long menuIdentification) {
        return mapper.selectSysRoleIdArrayByMenuId(menuIdentification).toArray(new Long[0]);
    }

    /**
     * 根据父级功能菜单编号查询子级功能菜单
     *
     * @param parentId - 父级功能菜单标识
     * @return List<SysMenuVO>
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/16 09:30
     */
    @Override
    public List<SysMenuVO> selectSysMenuListByParentId(final Long parentId) {
        List<SysMenu> sysMenuList = mapper.selectList(Wrappers.<SysMenu>lambdaQuery().eq(SysMenu::getParentId, parentId).orderByDesc(SysMenu::getSortNo));
        return SysMenuConverter.INSTANCE.listPo2listVo(sysMenuList);
    }

    /**
     * 根据功能菜单编号逻辑删除功能菜单
     *
     * @param menuIdentification - 父级功能菜单标识
     * @return Boolean
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/16 09:30
     */
    @Override
    public Boolean deleteMenuById(final Long menuIdentification) {
//        影响行数
        int change = mapper.changeMenuDelFlagByIdentification(CommonConstant.DEL_FLAG_DELETE, menuIdentification);
        return change > 0;
    }

    /**
     * 根据功能菜单编号修改功能菜单信息
     *
     * @param sysMenuUpdateRO - 功能菜单修改对象
     * @return Boolean
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/16 09:30
     */
    @Override
    public Boolean updateByMenuIdentification(final SysMenuUpdateRO sysMenuUpdateRO) {
        int update = mapper.updateByMenuIdentification(SysMenuConverter.INSTANCE.updateRo2domain(sysMenuUpdateRO));
        return update > 0;
    }

    /**
     * 根据功能菜单名称获取下拉
     *
     * @param menuName - 功能菜单名称
     * @return List<DropDownBoxTreeVO>
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/30 12:01
     */
    @Override
    public List<DropDownBoxTreeVO> queryMenuTreeByMenuName(final String menuName) {
        // 查询功能菜单
        List<SysMenu> sysOrganizationList = mapper.queryMenuTreeByMenuName(menuName);
        // 功能菜单转成下拉对象
        List<DropDownBoxTreeVO> dropDownBoxTreeVOList = SysMenuConverter.INSTANCE.po2BoxTreeVo(sysOrganizationList);
        // 生成下拉树
        List<DropDownBoxTreeVO> downBoxTreeVOList = generateDropDownBoxTree(dropDownBoxTreeVOList);
        return downBoxTreeVOList;
    }

}